import { ServiceException } from './../../common/excpetion/serviceException';
import { UserService } from './../../service/userService';
import { ApiDataContext } from './../../domain/apiDataContext';
import { Transaction } from 'tiny-entity2';
import { DataChangeLog, DataChangeLogStatus } from './../../domain/models/dataChangeLog';
import { ServiceManager } from './../../common/serviceFactory/serviceManager';
import * as Koa from 'koa';
import { route, RouteOptionsBase, RouteOptionsVerify, UsingLock } from "../../common";
import { DataChangeLogService } from '../../service/dataChangeLogService';
import { DataRegisterService } from '../../service/dataRegisterService';

const dataSvr = ServiceManager.Current.GetService<DataChangeLogService>('DataChangeLogService');
const dsSvr = ServiceManager.Current.GetService<DataRegisterService>('DataRegisterService');
const userSvr = ServiceManager.Current.GetService<UserService>('UserService');

class DataChangeLogController {
    @route(new RouteOptionsVerify('GET', '/api/dataChangeLog'))
    async queryDataChangeLogs(ctx: Koa.Context, next) {
        const orgId = ctx.headers['orgid'];
        let queryParams = ctx.query;
        if (!queryParams.orgId) {
            queryParams.orgId = orgId;
        }
        ctx.response.body = await dataSvr.QueryDataChangeLog(queryParams);
        await next();
    }
    @route(new RouteOptionsVerify('GET', '/api/dataChangeLog/:id'))
    async getDataChangeLogInfoById(ctx: Koa.Context, next) {
        ctx.response.body = null;
        await next();
    }
    @route(new RouteOptionsVerify('POST', '/api/dataChangeLog'))
    async createDataChangeLog(ctx: Koa.Context, next) {
        const orgId = ctx.headers['orgid'];

        let data: DataChangeLog = ctx.request.body;

        await UsingLock(data.id, async () => {
            return await Transaction(new ApiDataContext(), async ctx => {

                const inReviewList = await dataSvr.QueryDataChangeLog({
                    status: DataChangeLogStatus.InReview,
                    orgId,
                    dataRegisterId: data.dataRegisterId
                });

                if (inReviewList.length > 0) {
                    throw new ServiceException('无法添加，已经存在正在审核中的更正记录！');
                }

                data.createTime = Date.now();
                data.updateTime = Date.now();
                data.orgId = orgId;


                await dataSvr.CreateDataChangeLog(data, ctx);

                if (data.status == DataChangeLogStatus.Pass) {
                    await passDataChangeLog(data, ctx);
                }

            })
        });

        ctx.response.body = data;
        await next();
    }
    @route(new RouteOptionsVerify('PUT', '/api/dataChangeLog'))
    async updateDataChangeLog(ctx: Koa.Context, next) {
        const orgId = ctx.headers['orgid'];
        let data: DataChangeLog = ctx.request.body;

        await UsingLock(data.id, async () => {
            data.updateTime = Date.now();
            data.orgId = orgId;

            return await dataSvr.UpdateDataChangeLog(data);
        });

        ctx.response.body = null;
        await next();
    }

    @route(new RouteOptionsVerify('PUT', '/api/dataChangeLog/:id/status/:status'))
    async updateDataChangeLogStatus(ctx: Koa.Context, next) {
        let dataChangeLogId = ctx.params.id;
        let status = ctx.params.status;

        const dataChangeLog = await dataSvr.GetDataChangeLogById(dataChangeLogId);

        await UsingLock(dataChangeLogId, async () => {
            await Transaction(new ApiDataContext(), async ctx => {
                dataChangeLog.updateTime = Date.now();
                dataChangeLog.status = status;
                if (status == DataChangeLogStatus.Pass) {
                    await passDataChangeLog(dataChangeLog, ctx);
                }

                await dataSvr.UpdateDataChangeLog(dataChangeLog, ctx);
            })
        });

        ctx.response.body = dataChangeLog;

        await next();
    }

    @route(new RouteOptionsBase('PUT', '/api/dataChangeLog/syncdata/:projectId'))
    async syncNKData(ctx: Koa.Context, next) {
        let projectId = ctx.params.projectId;
        const dataSyncResult = await dsSvr.dataSync(projectId);
        ctx.response.body = dataSyncResult;
        await next();
    }
    @route(new RouteOptionsBase('PUT', '/api/dataChangeLog/synccontractdata/:projectId'))
    async syncSupplierContractData(ctx: Koa.Context, next) {
        let projectId = ctx.params.projectId;
        const dataSyncResult = await dsSvr.contractDataSync(projectId);
        ctx.response.body = dataSyncResult;
        await next();
    }
    @route(new RouteOptionsVerify('DELETE', '/api/dataChangeLog'))
    async deleteDataChangeLog(ctx: Koa.Context, next) {
        ctx.response.body = null;
        await next();
    }
}

const passDataChangeLog = async (data: DataChangeLog, ctx: ApiDataContext) => {
    const dataRegister = await dsSvr.GetDataRegisterById(data.dataRegisterId);
    const fields = dataRegister.data.fields
    for (let key in data.data) {
        fields[key] = data.data[key].targetValue;
    }
    dataRegister.updateTime = Date.now();
    await dsSvr.UpdateDataRegister(dataRegister, ctx);
}